package controllers;

import models.*;
import notifiers.*;
import play.mvc.*;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import play.data.validation.*;
import play.modules.gae.*;

public class Decks extends Application {

    @Before
    static void checkConnected() {
        if (GAE.getUser() == null) {
            Application.login();
        } else {
            renderArgs.put("user", GAE.getUser().getEmail());
        }
    }

    public static void index() {
        Collection<Deck> decks = Deck.findByUser(getUser());
        List<Game> uncompletedGames = Game.findAllUncompleted();
        render(decks, uncompletedGames);
    }

    public static void show(Long id) {
        Deck deck = Deck.findById(id);
        notFoundIfNull(deck);
        checkOwner(deck);
        Collection<Card> cards = deck.getCards();
        render(deck, cards);
    }

    public static void export(Long id) {
        Deck deck = Deck.findById(id);
        notFoundIfNull(deck);
        checkOwner(deck);
        String text = deck.toText();
        render(deck, text);
    }

    public static void importText(String text) {
        Deck.fromText(GAE.getUser().getEmail(), text);
        index();
    }

    public static void startImport() {
        render();
    }

    public static void blank() {
        render();
    }

    public static void create(@Required String name, String notes) {
        if (validation.hasErrors()) {
            flash.error("Oops, please give a name to your new deck");
            blank();
        }
        Deck deck = new Deck(getUser(), name);
        deck.notes = notes;
        deck.insert();
        index();
    }

    public static void delete(Long id) {
        Deck deck = Deck.findById(id);
        notFoundIfNull(deck);
        checkOwner(deck);

        ArrayList<Game> games = new ArrayList<Game>();
        for (Card card : deck.getCards()) {
            games.addAll(card.getGames());
        }

        if (games.size() == 0) {
            deck.delete();
            flash.success("The deck %s has been deleted", deck);
        } else {
            flash.error("Unable to delete deck. One or more card is part of ongoing game(s)", deck);
        }

        index();
    }

    public static void edit(Long id) {
        Deck deck = Deck.findById(id);
        notFoundIfNull(deck);
        checkOwner(deck);
        render(deck);
    }

    public static void save(Long id, @Required String name, String notes) {
        if (validation.hasErrors()) {
            params.flash();
            flash.error("Oops, please give a name to your deck");
            edit(id);
        }
        Deck deck = Deck.findById(id);

        notFoundIfNull(deck);
        checkOwner(deck);
        deck.name = name;
        deck.notes = notes;
        deck.update();

        index();
    }

    public static void addItem(Long id, String question, String answer) {
        Deck deck = Deck.findById(id);
        notFoundIfNull(deck);
        checkOwner(deck);
        new Card(deck, question, answer).insert();
        deck.update();
        show(id);
    }


    public static void deleteItem(Long id, Long cardId) {
        Card card = Card.findById(cardId);
        notFoundIfNull(card);
        checkOwner(card.getDeck());

        if(card.inOngoingGame()) {
            flash.error("Unable to delete card. Card is in ongoing game.");
        } else {
            card.delete();
        }

        show(id);
    }



    public static void editCard(Long cardId) {



        Card card = Card.findById(cardId);
        String question = card.getQuestion();
        String answer = card.getAnswer();

        params.put("question", question);
        params.put("answer", answer);

        render(card);
    }

    public static void updateCard(Long cardId, String question, String answer) {
        Card card = Card.findById(cardId);

        card.setAnswer(answer);
        card.setQuestion(question);

        card.update();

        flash.success("Card updated.");
        show(card.getDeck().id);
    }


    public static void email(Long id) {
        Deck deck = Deck.findById(id);
        notFoundIfNull(deck);
        checkOwner(deck);
        Notifier.emailList(deck);
        flash.success("This deck has been emailed to %s", deck.user);
        show(id);
    }

    // ~~~~~~ utils

    static String getUser() {
        return renderArgs.get("user", String.class);
    }

    static void checkOwner(Deck deck) {
        String user = getUser();
        if (!user.equals(deck.user)) {
            forbidden();
        }
    }


}

